﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using Medianamik.Core;
using Medianamik.Core.Urls;
using Medianamik.Globalization;
using Telerik.Web.UI;
using AllControls = Medianamik.Core.Sugar.Recurser<System.Web.UI.Control,
   System.Web.UI.ControlCollection>;

namespace Medianamik.UI.Controls
{
    public class URLCreator : BaseMedianamikControl
    {
        readonly Repeater _repeater = new Repeater();
        readonly System.Web.UI.WebControls.DropDownList _websites = new System.Web.UI.WebControls.DropDownList();
        readonly System.Web.UI.WebControls.DropDownList _indexation = new System.Web.UI.WebControls.DropDownList();
        readonly Button _addButton = new Button();
        readonly TextBox _path = new TextBox();
        readonly CustomValidator _validator = new CustomValidator();
        private readonly IUrlDictionary _urlDictionary = new ObjectFactory<IUrlDictionary>().Get();
        private IMedianamikUrl _newUrl;

        void RemoveUrlClick(Object sender, EventArgs e)
        {
            EnsureChildControls();

            var urls = GetUrlsFromRepeater().ToList();
            var url = GetUrlFromRepeaterItem(_repeater
                .Items[((RepeaterItem)((Control)sender)
                .NamingContainer).ItemIndex]);

            urls.Remove(url);

            _repeater.DataSource = urls;
            _repeater.DataBind();

            ResetFields();
        }

        void AddUrlClick(object sender, EventArgs e)
        {
            Page.Validate("URLCreator");

            if (Page.IsValid)
            {
                var urls = GetUrlsFromRepeater().ToList();

                //_newUrl est créé lors de la validation (hmmmm...)
                urls.Add(_newUrl);

                _repeater.DataSource = urls;
                _repeater.DataBind();
                ResetFields();
            }
        }

        void SyndicatedNodeTree_ValueChanged(object sender, ValueChangedEventArgs e)
        {
            _repeater.DataSource = new List<IMedianamikUrl>();
            _repeater.DataBind();
            ResetFields();
        }

        //TODO: Doit valider l'ensemble des urls pour l'unicité (à la sauvegarde de la page)
        //TODO: Valide UNE url (unicité / patron / champs requis) (à l'ajout d'une url manuellement)
        void _validator_ServerValidate(object source, ServerValidateEventArgs args)
        {
            bool valid = true;

            if (String.IsNullOrEmpty(_path.Text))
            {
                valid = false;
                _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorUrlMandatoryField");
            }
            else
            {
                WebSite webSite = null;
                if (!CurrentType.HasMultipleTemplates)
                    webSite = CurrentSite;

                if (webSite == null || CurrentType.HasMultipleTemplates)
                {
                    if (_websites.SelectedIndex < 1)
                    {
                        valid = false;
                        _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorWebSiteMandatoryField");
                    }
                    else
                        webSite = ConfigManager.Get<WebSite>(new Guid(_websites.SelectedValue));
                }

                if (webSite == null)
                {
                    valid = false;
                    _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorWebSiteMandatoryField");
                }
                else
                {
                    _newUrl = new MedianamikUrl(webSite, CurrentEditionCulture,
                        _path.Text, _indexation.SelectedIndex > 0);

                    var urls = GetUrlsFromRepeater();

                    if (urls.Contains(_newUrl))
                    {
                        valid = false;
                        _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorExistingUrl");
                    }
                    else
                    {
                        if (!_urlDictionary.UrlIsValid(_newUrl.Path))
                        {
                            valid = false;
                            _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorInvalidUrl");
                        }
                        else
                        {
                            if(CurrentNode == null)
                            {
                                if (!_urlDictionary.UrlIsUniqueForWebSite(_newUrl))
                                {
                                    valid = false;
                                    _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorExistingUrl");
                                }
                            }
                            else
                            {
                                if (!_urlDictionary.UrlIsUniqueForNode(_newUrl, CurrentNode.ID))
                                {
                                    valid = false;
                                    _validator.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorExistingUrl");
                                }
                            }
                        }
                    }
                }
            }

            args.IsValid = valid;
        }

        public override Type TypeOfValue
        {
            get { return typeof(string); }
        }

        public override bool AutoGenerateValidators
        {
            get
            {
                return false;
            }
            set
            {
                ;
            }
        }

        protected override bool WrapContentInParagraph
        {
            get
            {
                return false;
            }
        }

        private List<WebSite> _webSites;
        public List<WebSite> WebSites
        {
            get
            {
                if (_webSites == null)
                {
                    _webSites = ConfigManager.GetAllWebSites(MedianamikContext.Current.EditionCulture).ToList();
                }

                return _webSites;
            }
        }

        protected Node SyndicatedNode
        {
            get
            {
                if (IsSyndication && _syndicatedNode == null && SyndicatedNodeTree != null)
                {
                    object value = SyndicatedNodeTree.GetValue();
                    if (value != null)
                        _syndicatedNode = NodeManager.GetNode(new Guid(value.ToString()));
                }

                return _syndicatedNode;
            }
        }
        Node _syndicatedNode;

        protected ComboTreeWithPostBack SyndicatedNodeTree
        {
            get
            {
                if (_checkHasBeenDone == false && _syndicatedNodeTree == null)
                {
                    _checkHasBeenDone = true;
                    if (IsSyndication)
                    {
                        Control container = null;
                        Control parent = Parent;
                        while (parent != null && container == null)
                        {
                            if (parent is MedianamikFormTemplate || parent is RadMultiPage)
                            {
                                container = parent;
                            }
                            parent = parent.Parent;
                        }

                        if (container != null)
                        {
                            //FindControl is broken
                            //_syndicatedNodeTree = container.FindControlR(MedianamikProperties.SyndicatedNode.ToString()) as ComboTreeWithPostBack;

                            _syndicatedNodeTree = FindControl(container, MedianamikProperties.SyndicatedNode.ToString("N")) as ComboTreeWithPostBack;
                        }
                    }
                }
                return _syndicatedNodeTree;
            }
        }

        ComboTreeWithPostBack _syndicatedNodeTree;
        private bool _checkHasBeenDone;

        protected override bool SpecialLabel
        {
            get { return true; }
        }

        protected CultureInfo CurrentEditionCulture
        {
            get
            {
                if (_currentEditionCulture == null)
                    _currentEditionCulture = new CultureInfo(EditionCultureName);

                return _currentEditionCulture;
            }
        }
        private CultureInfo _currentEditionCulture;

        private void ResetFields()
        {
            if (_websites.Visible)
                _websites.SelectedIndex = 0;
            _path.Text = "";
            _repeater.Visible = _repeater.Items.Count > 0;
            _indexation.SelectedIndex = 0;
        }

        protected override void CreateControlHierarchy(bool databind)
        {
            if (IsSyndication && SyndicatedNodeTree != null)
                SyndicatedNodeTree.ValueChanged += SyndicatedNodeTree_ValueChanged;


            var mainLabel = new Literal();
            Controls.Add(mainLabel);

            var secondaryLabel = new Literal();
            Controls.Add(secondaryLabel);



            var startTableLiteral = new Literal();
            Controls.Add(startTableLiteral);



            Controls.Add(_websites);
            _websites.ID = "WebsiteControl";



            var midTable1Literal = new Literal();
            Controls.Add(midTable1Literal);



            Controls.Add(_path);
            _path.ID = "PathControl";



            var midTable2Literal = new Literal();
            Controls.Add(midTable2Literal);



            Controls.Add(_indexation);
            _websites.ID = "IndexationControl";



            var midTable3Literal = new Literal();
            Controls.Add(midTable3Literal);



            Controls.Add(_addButton);
            _addButton.Click += AddUrlClick;
            Controls.Add(new LiteralControl("&nbsp;"));
            Controls.Add(_validator);
            _validator.ServerValidate += _validator_ServerValidate;
            _validator.ControlToValidate = _path.ID;
            _validator.ValidateEmptyText = true;



            var endTableLiteral = new Literal();
            Controls.Add(endTableLiteral);



            Controls.Add(_repeater);
            _repeater.ItemTemplate = new UrlCreatorItemTemplate(RemoveUrlClick, (CurrentSite == null || CurrentType.HasMultipleTemplates));
            _repeater.HeaderTemplate = new UrlCreatorUrlListHeaderTemplate();
            _repeater.FooterTemplate = new UrlCreatorUrlListFooterTemplate();


            if (databind)
            {

                mainLabel.Text = "<h3>" + Label + " " + LabelExtensionText + "</h3>";

                secondaryLabel.Text = "<h4>" + Translator.Translate("Medianamik_ContentManagement",
                    "UrlCreatorSecondaryLabel") + "</h4>";




                if (CurrentSite == null || CurrentType.HasMultipleTemplates)
                {

                    startTableLiteral.Text = @"
                <table border=""0"" cellspacing=""0"" cellpadding=""0"" class=""TableauFormulaire"">
	                <tr>
                        <td width=""160"">
			                Site
		                </td>
		                <td width=""210"">
			                Url
		                </td>
		                <td>&nbsp;</td>
	                </tr>
	                <tr>
		                <td>";
                }
                else
                {
                    startTableLiteral.Text = @"
                <table border=""0"" cellspacing=""0"" cellpadding=""0"" class=""TableauFormulaire"">
	                <tr>
		                <td width=""210"">
			                Url
		                </td>
		                <td>&nbsp;</td>
	                </tr>
	                <tr>
		                <td>";
                }




                _path.CssClass = "TxtBox";
                _path.Attributes.Add("style", "width:200px");




                if (CurrentSite == null || CurrentType.HasMultipleTemplates)
                {
                    midTable1Literal.Text = @"</td>
                        <td>";
                }
                else
                {
                    midTable1Literal.Visible = false;
                }



                if (CurrentSite == null || CurrentType.HasMultipleTemplates)
                {
                    _websites.DataTextField = "DisplayName";
                    _websites.DataValueField = "ID";
                    _websites.CssClass = "SelectList";
                    _websites.Attributes.Add("style", "width:150px");

                    foreach (var site in WebSites)
                    {
                        var item = new ListItem(site.DisplayName, site.ID.ToString());

                        if (CurrentSite != null)
                            item.Selected = site.ID.Equals(CurrentSite.ID);

                        _websites.Items.Add(item);
                    }

                    _websites.Items.Insert(0, "");
                }
                else
                {
                    _websites.Visible = false;
                }



                midTable2Literal.Text = @"</td>
                        <td>";



                _indexation.CssClass = "SelectList";
                _indexation.Attributes.Add("style", "width:150px");
                _indexation.Items.Add(new ListItem(Translator.Translate("Medianamik_ContentManagement", "Indexed"), "False"));
                _indexation.Items.Add(new ListItem(Translator.Translate("Medianamik_ContentManagement", "NotIndexed"), "True"));



                midTable3Literal.Text = @"</td>
                        <td>";




                _addButton.ValidationGroup = "URLCreator";
                _addButton.Text = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorAddButton");
                _addButton.CssClass = "Btn";
                _validator.ErrorMessage = Translator.Translate("Medianamik_ContentManagement", "UrlCreatorUrlInvalid");
                _validator.ValidationGroup = "URLCreator";
                _validator.Display = ValidatorDisplay.Dynamic;
                _validator.EnableClientScript = false;



                endTableLiteral.Text = @"
                            </td>
	                    </tr>
                    </table>";



                _repeater.DataSource = GetUrlsFromXDocument(DataSource);
                _repeater.DataBind();
                _repeater.Visible = _repeater.Items.Count > 0;

            }
        }

        public override object GetValue()
        {
            EnsureChildControls();

            var nodeId = NodeId;

            if (IsSyndication)
            {
                nodeId = SyndicatedNode.ID;
            }

            return GetUrlsFromRepeater().GetXmlFromUrls(nodeId);
        }

        protected Control FindControl(Control container, string id)
        {
            foreach (Control control in AllControls.TopDown(container.Controls))
            {
                if (control.ID.Equals(id))
                {
                    return control;
                }
            }

            return null;
        }

        private IEnumerable<IMedianamikUrl> GetUrlsFromXDocument(object document)
        {
            var urls = new List<IMedianamikUrl>();

            if (document == null || document.ToString().Length == 0)
                return urls;

            return UrlHelper.GetUrlsFromXml(document.ToString(), CurrentEditionCulture);
        }

        private IEnumerable<IMedianamikUrl> GetUrlsFromRepeater()
        {
            foreach (RepeaterItem item in _repeater.Items)
            {

                yield return GetUrlFromRepeaterItem(item);
            }
        }

        private IMedianamikUrl GetUrlFromRepeaterItem(RepeaterItem item)
        {
            var urlPath = item.FindControl("UrlPath") as HiddenField;
            var websiteId = item.FindControl("WebSiteId") as HiddenField;
            var excludedFromIndexation = item.FindControl("ExcludedFromIndexation") as System.Web.UI.WebControls.DropDownList;
            return new MedianamikUrl(new Guid(websiteId.Value), CurrentEditionCulture,
                urlPath.Value, excludedFromIndexation.SelectedIndex > 0);
        }
    }

    public class UrlCreatorItemTemplate : ITemplate
    {
        Literal _url;
        Button _removeButton;
        readonly EventHandler<EventArgs> _removeUrlEventHandler;
        readonly bool _multiWebSites;
        System.Web.UI.WebControls.DropDownList _excludedFromIndexation;
        HiddenField _path;
        HiddenField _websiteId;

        public UrlCreatorItemTemplate(EventHandler<EventArgs> removeUrlEventHandler,
            bool multiWebSites)
        {
            _removeUrlEventHandler = removeUrlEventHandler;
            _multiWebSites = multiWebSites;
        }

        void UrlDataBinding(object sender, EventArgs e)
        {
            var container = (RepeaterItem)_url.NamingContainer;
            var url = container.DataItem as IMedianamikUrl;
            if (url != null)
            {


                _url.Text = (_multiWebSites ? ConfigManager.GetWebSite(url.WebsiteId, url.Culture).DisplayName + " --&gt; " : String.Empty)
                            + url.Path;

                _excludedFromIndexation.Items.Add(new ListItem(Translator.Translate("Medianamik_ContentManagement", "Indexed"), "False"));
                _excludedFromIndexation.Items.Add(new ListItem(Translator.Translate("Medianamik_ContentManagement", "NotIndexed"), "True"));

                _excludedFromIndexation.SelectedIndex = url.ExcludedFromIndexation ? 1 : 0;

                _path.Value = url.OriginalPath;

                _websiteId.Value = url.WebsiteId.ToString();
            }
        }

        public void InstantiateIn(Control container)
        {
            container.Controls.Add(new LiteralControl("<tr><td style=\"padding-right:10px; vertical-align:middle;\">"));

            _url = new Literal();
            container.Controls.Add(_url);
            _url.DataBinding += UrlDataBinding;

            container.Controls.Add(new LiteralControl("</td><td>"));

            _excludedFromIndexation = new System.Web.UI.WebControls.DropDownList
                                          {
                                              ID = "ExcludedFromIndexation",
                                              CssClass = "SelectList"
                                          };
            _excludedFromIndexation.Attributes.Add("style", "width:150px");
            container.Controls.Add(_excludedFromIndexation);

            container.Controls.Add(new LiteralControl("</td><td>"));

            _removeButton = new Button
                                {
                                    CssClass = "Btn",
                                    Text = Translator.Translate("Medianamik_ContentManagement",
                                                                "UrlCreatorDeleteUrl")
                                };
            _removeButton.Click += new EventHandler(_removeUrlEventHandler);
            container.Controls.Add(_removeButton);
            _path = new HiddenField { ID = "UrlPath" };
            container.Controls.Add(_path);

            _websiteId = new HiddenField { ID = "WebSiteId" };
            container.Controls.Add(_websiteId);

            container.Controls.Add(new LiteralControl("</td></tr><tr><td colspan=\"3\" style=\"height:5px;\"></td></tr>"));
        }
    }

    public class UrlCreatorUrlListHeaderTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            container.Controls.Add(new LiteralControl("<h4>" +
                Translator.Translate("Medianamik_ContentManagement",
                "UrlCreatorUrlListLabel") + "</h4><table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"TableauFormulaire\">"));
        }
    }

    public class UrlCreatorUrlListFooterTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            container.Controls.Add(new LiteralControl("</table>"));
        }
    }
}